package com.nineclock.attendance.service.impl;
import java.sql.Timestamp;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.attendance.dto.AttendGroupDTO;
import com.nineclock.attendance.dto.AttendHolidayDTO;
import com.nineclock.attendance.dto.AttendOvertimeRuleDTO;
import com.nineclock.attendance.dto.AttendOvertimeRuleDetailDTO;
import com.nineclock.attendance.mapper.AttendGroupMapper;
import com.nineclock.attendance.mapper.AttendHolidayMapper;
import com.nineclock.attendance.mapper.AttendOvertimeRuleDetailMapper;
import com.nineclock.attendance.mapper.AttendOvertimeRuleMapper;
import com.nineclock.attendance.pojo.AttendGroup;
import com.nineclock.attendance.pojo.AttendHoliday;
import com.nineclock.attendance.pojo.AttendOvertimeRule;
import com.nineclock.attendance.pojo.AttendOvertimeRuleDetail;
import com.nineclock.attendance.service.AttendHolidayService;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class AttendHolidayServiceImpl implements AttendHolidayService {

    @Autowired(required = false)
    private AttendHolidayMapper holidayMapper;

    @Autowired(required = false)
    private AttendOvertimeRuleMapper overtimeRuleMapper;

    @Autowired(required = false)
    private AttendGroupMapper attendGroupMapper;

    @Autowired(required = false)
    private AttendOvertimeRuleDetailMapper attendOvertimeRuleDetailMapper;
    @Override
    public PageResult<AttendHolidayDTO> queryHoliday(Integer page, Integer pageSize) {

        IPage<AttendHoliday> ipage = new Page<>(page,pageSize);
        LambdaQueryWrapper<AttendHoliday> warpper = new LambdaQueryWrapper<>();
        warpper.eq(AttendHoliday::getCompanyId, CurrentUserHolder.get().getCompanyId());
        ipage = holidayMapper.selectPage(ipage, warpper);
        List<AttendHoliday> holidayList = ipage.getRecords();
        List<AttendHolidayDTO> attendHolidayDTOS = BeanHelper.copyWithCollection(holidayList, AttendHolidayDTO.class);

        return new PageResult<>(ipage.getTotal(),ipage.getPages(),attendHolidayDTOS);
    }

    @Override
    public PageResult<AttendOvertimeRuleDTO> queryOverTime(Integer page, Integer pageSize) {
        IPage<AttendOvertimeRule> iPage=new Page(page,pageSize);

        LambdaQueryWrapper<AttendOvertimeRule> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(AttendOvertimeRule::getCompanyId,CurrentUserHolder.get().getCompanyId());
        iPage = overtimeRuleMapper.selectPage(iPage, wrapper);
        List<AttendOvertimeRule> records = iPage.getRecords();
        List<AttendOvertimeRuleDTO> collect = records.stream().map(attendOverTimeRule -> {
            AttendOvertimeRuleDTO attendOvertimeRuleDTO = getAttendOvertimeRuleDTO(attendOverTimeRule);
            return attendOvertimeRuleDTO;
    }).collect(Collectors.toList());
        return new PageResult<>(iPage.getTotal(), iPage.getPages() ,collect);
}

    private AttendOvertimeRuleDTO getAttendOvertimeRuleDTO(AttendOvertimeRule attendOverTimeRule) {
        LambdaQueryWrapper<AttendGroup> wrapper1=new LambdaQueryWrapper<>();
        String[] split = attendOverTimeRule.getAttendGroupIds().split(",");
        List<Long> list=new ArrayList<>();
        for (String s : split) {
            list.add(Long.valueOf(s));
        }
        wrapper1.eq(AttendGroup::getCompanyId,CurrentUserHolder.get().getCompanyId());
        wrapper1.in(AttendGroup::getId,list);
        List<AttendGroup> attendGroups = attendGroupMapper.selectList(wrapper1);

        List<AttendGroupDTO> list1 = BeanHelper.copyWithCollection(attendGroups, AttendGroupDTO.class);
        AttendOvertimeRuleDTO attendOvertimeRuleDTO =
                BeanHelper.copyProperties(attendOverTimeRule, AttendOvertimeRuleDTO.class);
        attendOvertimeRuleDTO.setAttendGroups(list1);
        LambdaQueryWrapper<AttendOvertimeRuleDetail> wrapper2=new LambdaQueryWrapper<>();
        wrapper2.eq(AttendOvertimeRuleDetail::getOvertimeRuleId,attendOvertimeRuleDTO.getId());

        List<AttendOvertimeRuleDetail> attendOvertimeRuleDetails =
                attendOvertimeRuleDetailMapper.selectList(wrapper2);
        List<AttendOvertimeRuleDetailDTO> collect1 = attendOvertimeRuleDetails.stream().map(attendOvertimeRuleDetail -> {
            AttendOvertimeRuleDetailDTO attendOvertimeRuleDetailDTO = new AttendOvertimeRuleDetailDTO();
            attendOvertimeRuleDetailDTO.setRuleType(attendOvertimeRuleDetail.getType());
            attendOvertimeRuleDetailDTO.setId(attendOvertimeRuleDetail.getId());
            attendOvertimeRuleDetailDTO.setComputeType(attendOvertimeRuleDetail.getComputeType());
            return attendOvertimeRuleDetailDTO;
        }).collect(Collectors.toList());
        attendOvertimeRuleDTO.setRuleContent(collect1);
        return attendOvertimeRuleDTO;
    }

    @Override
    public AttendOvertimeRuleDTO queryOverTimeById(Long id) {
        AttendOvertimeRule attendOvertimeRule = overtimeRuleMapper.selectById(id);
        AttendOvertimeRuleDTO attendOvertimeRuleDTO = getAttendOvertimeRuleDTO(attendOvertimeRule);
        return attendOvertimeRuleDTO;
    }

    @Override
    public void deleteOverTimeById(Long id) {
        overtimeRuleMapper.deleteById(id);
    }

    @Override
    public void insert(AttendOvertimeRuleDTO overtimeRuleDTO) {
        AttendOvertimeRule attendOvertimeRule = BeanHelper
                .copyProperties(overtimeRuleDTO, AttendOvertimeRule.class);
        overtimeRuleMapper.insert(attendOvertimeRule);
        Long id = attendOvertimeRule.getId();
        insertOvertimeRuleDetail(overtimeRuleDTO,id);
    }

    private void insertOvertimeRuleDetail(AttendOvertimeRuleDTO overtimeRuleDTO, Long id) {
        AttendOvertimeRuleDetailDTO holiday = overtimeRuleDTO.getHoliday();
        AttendOvertimeRuleDetail ruleDetail=setDetail(holiday,id,3);
        attendOvertimeRuleDetailMapper.insert(ruleDetail);
        AttendOvertimeRuleDetailDTO playDay = overtimeRuleDTO.getPlayDay();
        AttendOvertimeRuleDetail ruleDetail1=setDetail(playDay,id,2);
        attendOvertimeRuleDetailMapper.insert(ruleDetail1);
        AttendOvertimeRuleDetailDTO workDay = overtimeRuleDTO.getWorkDay();
        AttendOvertimeRuleDetail ruleDetail2=setDetail(workDay,id,1);
        attendOvertimeRuleDetailMapper.insert(ruleDetail2);
    }

    private AttendOvertimeRuleDetail setDetail(AttendOvertimeRuleDetailDTO detailDTO, Long id, int i) {
        AttendOvertimeRuleDetail ruleDetail = new AttendOvertimeRuleDetail();
        ruleDetail.setType(i);
        ruleDetail.setOvertimeRuleId(id);
        ruleDetail.setAllow(detailDTO.getAllow()?(byte)1:(byte)0);
        if (detailDTO.getAllow()){
            ruleDetail.setComputeType(detailDTO.getComputeType());
            ruleDetail.setStartAfterOffWork(detailDTO.getStartAfterOffWork());
            ruleDetail.setLessMinutesCurDay(detailDTO.getLessMinutesCurDay());
        }
        ruleDetail.setAllowBanRest(detailDTO.getAllowBanRest()?(byte)1:(byte)0);
        if (detailDTO.getAllowBanRest()){
            ruleDetail.setBanRestType(detailDTO.getBanRestType());
            if (ruleDetail.getBanRestType()==1) {
                ruleDetail.setRestStartTime(detailDTO.getRestStartTime());
                ruleDetail.setRestEndTime(detailDTO.getRestEndTime());
            }else{
                ruleDetail.setMatchHours(detailDTO.getMatchHours());
                ruleDetail.setBanHours(detailDTO.getMatchHours());
            }
        }

        ruleDetail.setAllowMakeUp(detailDTO.getAllowMakeUp()?(byte)1:(byte)0);
        if (detailDTO.getAllowMakeUp()){
            ruleDetail.setMakeUpType(detailDTO.getMakeUpType());
        }
        return ruleDetail;
    }

    /**
     * 接口名称：考勤: 更新假期
     * 接口路径：GET/atte/rule/holiday/{id}
     */
    @Override
    public void updateHoliday(Long id, AttendHolidayDTO holidayDTO) {
        AttendHoliday attendHoliday = BeanHelper.copyProperties(holidayDTO, AttendHoliday.class);
        attendHoliday.setUpdateTime(new Timestamp(new java.util.Date().getTime()));
        holidayMapper.updateById(attendHoliday);
    }

    /**
     * 接口名称：考勤: 删除假期
     * 接口路径：Delete/atte/rule/holiday/{id}
     */
    @Override
    public void removeHoliday(Long id) {
        if (id == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        holidayMapper.deleteById(id);
    }

    /**
     * 接口名称：考勤: 添加假期
     * 接口路径：Post/atte/rule/holiday
     */
    @Override
    public void addHoliday(HashMap<String, Object> map) {
        AttendHoliday holiday = new AttendHoliday();
        holiday.setName(map.get("name").toString());
        holiday.setApplyUnit(Integer.valueOf(map.get("applyUnit").toString()));
        holiday.setHoursADay(Integer.valueOf(map.get("hoursADay").toString()));
        holiday.setAccountingType(Integer.valueOf(map.get("accountingType").toString()));
        holiday.setGivingType(Integer.valueOf(map.get("givingType").toString()));
        holiday.setGivingDate(map.get("givingDate").toString());
        holiday.setAmountRuleType(Integer.valueOf(map.get("amountRuleType").toString()));
        holiday.setFixedAmount(Integer.valueOf(map.get("fixedAmount").toString()));
        holiday.setValidityPeriod(Integer.valueOf(map.get("validityPeriod").toString()));
        holiday.setCompanyId(CurrentUserHolder.get().getCompanyId());
        holiday.setCreateTime(new Timestamp(new java.util.Date().getTime()));
        holiday.setUpdateTime(new Timestamp(new java.util.Date().getTime()));
        holiday.setRuleByServiceTime(map.get("ruleByServiceTime").toString());
        holidayMapper.insert(holiday);
    }


}
